
if (!("jsap" in window)) window.jsap = {};
if (!("xml" in window)) window.jsap.xml = {};

jsap.xml.XML = function(obj) {
    if (!(this instanceof jsap.xml.XML)) return new jsap.xml.XML(obj);
    this.obj = obj ;
    return this ;
}
jsap.xml.XML.ELEMENT_NODE = 1 ;
jsap.xml.XML.ATTRIBUTE_NODE = 2 ;
jsap.xml.XML.TEXT_NODE = 3 ;
jsap.xml.XML.CDATA_SECTION_NODE = 4 ;
jsap.xml.XML.ENTITY_REFERENCE_NODE = 5 ;
jsap.xml.XML.ENTITY_NODE = 6 ;
jsap.xml.XML.PROCESSING_INSTRUCTION_NODE = 7 ;
jsap.xml.XML.COMMENT_NODE = 8 ;
jsap.xml.XML.DOCUMENT_NODE = 9 ;
jsap.xml.XML.DOCUMENT_TYPE_NODE = 10 ;
jsap.xml.XML.DOCUMENT_FRAGMENT_NODE = 11 ;
jsap.xml.XML.NOTATION_NODE = 12 ;
jsap.xml.XML.prototype = {
    serializeToXML : function(xmlDocument, node) {
        if (this.obj == null) return xmlDocument.createTextNode("");
        if (typeof this.obj == "boolean") {
            node.appendChild(xmlDocument.createTextNode(this.obj + "" == "true" ? "true" : "false"));
            return node ;
        }
        if (typeof this.obj == "number") {
            node.appendChild(xmlDocument.createTextNode(this.obj));
            return node ;
        }
        if (typeof this.obj == "string") {
            try {
                node.appendChild(xmlDocument.createTextNode(new String(this.obj).replace(/&/g, "&amp;")));
            } catch(ex) {
                alert("this.obj [" + this.obj + "] ex [" + ex + "]");
            }
            return node ;
        }
        if (typeof this.obj == "object") {
            return this.serializeObject2XML(xmlDocument, node);
        }
    },
    serializeDOM2String : function() {
        var elem = this.obj ;
        if (elem.nodeType == 3) return elem.nodeValue ; // Text node
        if (elem.nodeType == 2) return elem.nodeName + "=\"" + elem.nodeValue + "\"" ; // Attribute
        var result = "<" ;
        result += elem.nodeName ;
        for (var i = 0, l = elem.attributes.length ; i < l ; i ++) {
            result += " " + jsap.xml.XML(elem.attributes[i]).serializeDOM2String();
        }
        if (elem.childNodes.length > 0) {
            result += ">" ;
            for (var i = 0, l = elem.childNodes.length ; i < l ; i ++) {
                result += jsap.xml.XML(elem.childNodes[i]).serializeDOM2String();
            }
            result += "</" + elem.nodeName + ">" ;
        } else {
            result += "/>" ;
        }
        return result ;
    },
    serializeToString : function(rootName) {
        if (this.obj && this.isXMLDoc(this.obj)) return this.serializeDOM2String();
        if (typeof this.obj == "object") return jsap.xml.XML(this.serializeObject2XML(null, rootName)).serializeToString();
        return this.obj + "" ;
    },
    isXMLDoc: function(elem) {
        return elem.documentElement && !elem.body ||
            elem.tagName && elem.ownerDocument && !elem.ownerDocument.body ; // from jQuery
    },
    serializeObject2XML : function(aXMLDocument, node) {
        var xmlDocument = aXMLDocument ? aXMLDocument : this.createXMLDocument();
        var rootNode = node && this.isXMLDoc(node) ? node : xmlDocument.createElement(typeof node == "string" ? node : "root");
        if (this.obj.serializeToXML) {
            this.obj.serializeToXML(xmlDocument, rootNode, function(aXMLDocument, aObj, aNode) {
                return jsap.xml.XML(aObj).serializeToXML(aXMLDocument, aNode);
            });
        }
        return rootNode ;
    },
    iterateNodeChildren : function(node) {
        if (this.obj.deserializeXML) {
            for (var i = 0, l = node.childNodes.length ; i < l ; i ++) {
                this.obj.deserializeXML(node.childNodes[i]);
            }
        }
    },
    createXMLDocument : function() {
        if (typeof this.obj == "string") {
            var doc ;
            if (window.ActiveXObject) {
                doc = new ActiveXObject("Microsoft.XMLDOM");
                doc.async = "false" ;
                doc.loadXML(this.obj);
            } else { // code for Mozilla, Firefox, Opera, etc.
                var parser = new DOMParser();
                doc = parser.parseFromString(this.obj, "text/xml");
            }
            return doc.documentElement ;
        } else {
            var xmlDoc ;
            // code for IE
            if (window.ActiveXObject) {
                xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
            }
            // code for Mozilla, Firefox, Opera, etc.
            else if (document.implementation &&
                        document.implementation.createDocument) {
                xmlDoc = document.implementation.createDocument("", "", null);
            } else {
                alert('Your browser cannot handle this script');
            }
            return xmlDoc ;
        }
    },
    getNodeText : function(node) {
        if (node.nodeType == 3) return node.nodeValue ;
        var result = "" ;
        if (node.childNodes.length > 0) {
            for (var i = 0, l = node.childNodes.length ; i < l ; i ++)
                result += jsap.xml.XML().getNodeText(node.childNodes[i]);
        }
        return result ;
    }
}

function a$(name, value) {
    if (value) {
        switch (name) {
            case "cellspacing" : this.cellSpacing = value ; break ;
            case "cellpadding" : this.cellPadding = value ; break ;
            case "width" : this.width = value ; break ;
            case "height" : this.height = value ; break ;
            case "border" : this.border = value ; break ;
            case "colspan" : this.colSpan = value ; break ;
            case "rowspan" : this.rowSpan = value ; break ;
            case "class" : this.cn$(value); return this ;
        }
        this.setAttribute(name, value);
    } else if (name) {
        //jsLog.debug("name [" + name + "]");
        if (name.substring(name.length - 1) == ">") {
            name = name.substring(0, name.length - 1);
            if (name.substring(name.length - 1) == "/") name = name.substring(0, name.length - 1);
        }
        var regItems = name.split(/=/);
        var key ;
        var nameValues = new jsap.util.HashMap();
        for (var i = 0, l = regItems.length ; i < l ; i ++) {
            switch (i) {
                case 0 : key = regItems[i] ; break ;
                case regItems.length - 1 : {
                    //jsLog.debug("[" + key + ", " + regItems[i].replace(/(^\s*)|(\s*$)/g, "") + "]");
                    nameValues.put(key, regItems[i].replace(/(^\s*)|(\s*$)/g, ""));
                } break ;
                default : {
                    var str = regItems[i] ;
                    var ix = str.lastIndexOf(" ");
                    //jsLog.debug("[" + key + ", " + str.substring(0, ix).replace(/(^\s*)|(\s*$)/g, "") + "]");
                    nameValues.put(key, str.substring(0, ix).replace(/(^\s*)|(\s*$)/g, ""));
                    key = str.substring(ix + 1);
                } break ;
            }
        }
        var keys = nameValues.keySet();
        for (var i = 0, l = keys.getLength(); i < l ; i ++) {
            var aName = keys.get(i);
            var aValue = nameValues.get(aName);
            if (aValue.charAt(0) == '\'' || aValue.charAt(0) == '\"') {
                aValue = aValue.substring(1);
                aValue = aValue.substring(0, aValue.length - 1);
            }
            //jsLog.debug("aName, aValue [" + aName + ", " + aValue + "]");
            this.a$(aName, aValue);
        }
    }
    return this ;
}
function ae$(child) { this.appendChild(child); return this ; }
function cn$(className) { this.className = className ; return this ; }
function css$() {
    var args = arguments ;
    if (args.length == 2) this.style[args[0]] = args[1] ;
    if (args.length == 1) {
        var aConfig = args[0] ;
        if (typeof aConfig == "object") {
            for (var name in aConfig) {
                this.style[name] = aConfig[name] ;
            }
        }
    }
    return this ;
}
function e$(name) {
    var ix = name.indexOf(" ");
    if (ix != -1) {
        var tagName = name.substring(0, ix);
        var attrs = name.substring(ix + 1);
        return e$(tagName).a$(attrs);
    } else {
        if (name.indexOf("<") == 0) name = name.substring(1);
        if (name.substring(name.length - 1) == ">") {
            name = name.substring(0, name.length - 1);
            if (name.substring(name.length - 1) == "/") name = name.substring(0, name.length - 1);
        }
        var elem = document.createElement(name);
        elem.a$ = a$ ;
        elem.cn$ = cn$ ;
        elem.ae$ = ae$ ;
        elem.css$ = css$ ;
        return elem ;
    }
}
function t$(text) {
    return document.createTextNode(text);
}